import {
  _decorator,
  Component,
  Collider2D,
  Contact2DType,
  UITransform,
  BoxCollider2D,
  RigidBody2D,
  Size,
  Label,
  Vec3,
  tween,
  instantiate,
  AudioClip,
} from 'cc'
import { GAME_EVENT_ENUM, GAME_STATUS_ENUM } from './Enums'
import { COMPLETE_IDIOMS } from './Events'
import { DataManager } from './DataManager'
import { AudioMgr } from './Utils/AudioMgr'
const { ccclass, property } = _decorator
function isAnagramSubset(combined, idiom) {
  if (combined.length !== idiom.length) return false

  const countMap = {}

  for (const ch of idiom) {
    countMap[ch] = (countMap[ch] || 0) + 1
  }

  for (const ch of combined) {
    if (!countMap[ch]) return false
    countMap[ch]--
  }

  return true
}

function getOrderedCombined(
  wordA: string,
  wordB: string,
  idioms: string[],
): string | null {
  for (const idiom of idioms) {
    const iA = idiom.indexOf(wordA)
    const iB = idiom.indexOf(wordB)
    if (iA !== -1 && iB !== -1) {
      return iA < iB ? wordA + wordB : wordB + wordA
    }
  }
  return null // 找不到排序依据
}

@ccclass('Block')
export class Block extends Component {
  @property(AudioClip)
  mergeSound: AudioClip = null!

  status: string = ''
  word: string = ''
  mergeWord: string[] = []

  private collider: BoxCollider2D = null!
  private rigidBody: RigidBody2D = null!
  protected onLoad(): void {
    this.node.getComponent(UITransform).width = this.word.length * 66
  }

  protected start(): void {
    this.collider = this.node.getComponent(BoxCollider2D)
    this.collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this)
    this.rigidBody = this.node.getComponent(RigidBody2D)
    if (this.collider) {
      const { width, height } = this.node.getComponent(UITransform)
      this.collider.size = new Size(width, height)
      this.collider.apply()
    }
    this.node.getChildByName('Label').getComponent(Label).string = this.word
  }
  onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D) {
    const otherBlock = otherCollider.getComponent(Block)
    // 触碰地面，或者当前 Block 的词序大于被触碰的 Block 的词序
    if (!otherBlock) return
    if (this.word > otherBlock.word) return
    const selfWord = this.word
    const otherWord = otherBlock.word
    const { idioms } = DataManager.inst

    // 基础合并尝试（默认 selfWord + otherWord）
    let combined = selfWord + otherWord

    // 获取合适的顺序（如举三 vs 三举）
    const ordered = getOrderedCombined(selfWord, otherWord, idioms)
    if (ordered) {
      combined = ordered
    }

    // 共同判断，处理连续字时要求在mergeWord中
    // 处理非连续字 例如 一 + 先 => /一.*?先/
    const pattern = combined.split('').join('.*?')
    const regex = new RegExp(pattern)
    const foundInAny = idioms.some(idiom => regex.test(idiom))
    // 被碰撞字位于 mergeWord 中
    const canMerge =
      this.mergeWord.includes(otherWord) || otherBlock.mergeWord.includes(selfWord)

    // 允许非连续组合，例如 一先 + 马当 => 一马当先
    const matchedIdiom = idioms.find(idiom => isAnagramSubset(combined, idiom))
    if (matchedIdiom) combined = matchedIdiom

    if (matchedIdiom || (foundInAny && canMerge)) {
      const pos1 = this.node.worldPosition
      const pos2 = otherBlock.node.worldPosition
      const midPos = new Vec3((pos1.x + pos2.x) / 2, (pos1.y + pos2.y) / 2, 0)

      // 将引用保存
      const isFull = idioms.includes(combined)

      // 使用父节点调度，避免被销毁
      const scheduler = this.node.parent?.getComponent(Component)
      scheduler?.scheduleOnce(() => {
        if (!this.node.isValid || !otherBlock.node.isValid) return
        this.node.destroy()
        otherBlock.node.destroy()
        this.createNewBlock(combined, midPos, isFull)
      }, 0)
    }
  }

  createNewBlock(word: string, position: Vec3, isFullIdiom: boolean) {
    const { blockPrefab, idiomNodes } = DataManager.inst
    const parentNode = this.node.parent
    const newBlock = instantiate(blockPrefab)
    parentNode.addChild(newBlock)
    newBlock.setWorldPosition(position)

    const newBlockScript = newBlock.getComponent(Block)
    newBlockScript.word = word

    // 设置 label 文本
    const label = newBlock.getChildByName('Label').getComponent(Label)
    if (label) label.string = word

    const uiTransform = newBlock.getComponent(UITransform)
    const collider = newBlock.getComponent(BoxCollider2D)
    const initialWidth = word.length * 66
    uiTransform.width = initialWidth
    collider.size = new Size(initialWidth, collider.size.height)
    collider.apply()
    AudioMgr.inst.playOneShot(this.mergeSound)

    if (isFullIdiom) {
      // ✅ 查找目标 idiomNode
      const target = idiomNodes.find(elem => elem.name === word)
      if (!target) {
        console.warn(`找不到成语 ${word} 的目标节点`)
        return
      }

      const targetPos = target.getWorldPosition()
      const targetSize = target.getComponent(UITransform)
      const targetWidth = targetSize?.width || initialWidth
      const targetHeight = targetSize?.height || uiTransform.height

      const duration = 0.6
      collider.enabled = false

      // 设置Clear状态
      DataManager.inst.gameStatus = GAME_STATUS_ENUM.CLEAR

      // 同时 tween 尺寸
      tween(uiTransform)
        .to(duration, { width: targetWidth, height: targetHeight })
        .start()

      // tween 移动
      tween(newBlock)
        .to(duration, { worldPosition: targetPos })
        .call(() => {
          COMPLETE_IDIOMS.emit(GAME_EVENT_ENUM.CHANGE_IDIOM, word)
          newBlock.destroy()
        })
        .start()
    }
  }
}
